#include "const.h"

static void initvars(int argc, char **argv) {
	char hostconfig[256];
	var_t v;
	int i;

	// initialize the variables system
	v_init();

	// create the arguments array
	v = v_new_array("args", "arg", argc-1);
	for(i=1; i<argc; i++)
		v_array_push(v, argv[i]);

	// set the cpu count (possibly useful for tool invocations)
	v_setvar("cpucount", va("%d", getcpucount()));

	// store the configuration directory
	v_setvar("configdir", getconfigdir());

	// specify the host configuration
	v_nformat(hostconfig, sizeof(hostconfig), "$(hostsys).$(hostarch)");
	v_setvar("hostconfig", hostconfig);
}

static void initdefopts() {
	// NOTE: set "opthasarg.<optname>" to "yes" if an argument is expected
	// NOTE: set "optlong.<optchar>" to "<optname>" if <optchar> is a shortcut

	v_setvar("optlong.h",   "help");
	v_setvar("optlong.v",   "version");
	v_setvar("optlong.V",   "verbose");

	v_setvar("opt.help",    "no");
	v_setvar("opt.version", "no");
	v_setvar("opt.verbose", "no");
}

static void initopts(int argc, char **argv) {
	const char *temp;
	var_t goals, files;
	char buf[256];
	char *opt, *p;
	int i, r;

	goals = v_new_array("goals", "goal", 8);
	files = v_new_array("projectfiles", "projectfile", 1);

	//v_set(goals, "");
	//v_set(files, "");

	for(i=1; i<argc; i++) {
		opt = argv[i];

		// look for goals
		if(!strcmp(opt, "clean")
		|| !strcmp(opt, "backup")
		|| !strcmp(opt, "debug")
		|| !strcmp(opt, "release")
		|| !strcmp(opt, "package")
		|| !strcmp(opt, "install")
		|| !strcmp(opt, "emulate")
		|| !strcmp(opt, "test")
		|| !strcmp(opt, "run")) {
			// add to the list of goals
			v_array_push(goals, opt);
			continue;
		}

		// is this an option?
		if (opt[0]=='-') {
			// long name?
			if (opt[1]=='-') {
				opt = &opt[2];

				// is the setting part of the argument's name?
				if ((p = strchr(opt, '=')) != (char *)0) {
					i_strncpy(buf, sizeof(buf), opt, p-opt);
					setopt(buf, &p[1]);
				} else {
					// are we cancelling an option?
					if (!strncmp(opt, "no-", 3)) {
						opt = &opt[3];
						r = 0;
					} else
						r = 1;

					// check if the option takes an argument
					temp = v_format(va("$(opthasarg.%s)", opt));
					if (!strcmp(temp, "yes")) {
						// was the option passed in as "no-option?"
						if (!r) {
							fprintf(stderr,
								"warning: invalid use of 'no-' prefix on "
								"\"%s\"\n", opt);
							fflush(stderr);
						}

						// was an argument given?
						if (i+1 < argc) {
							setopt(opt, argv[++i]);
						} else {
							fprintf(stderr,
								"warning: option expects argument\n");
							fflush(stderr);
						}
					} else
						// set the appropriate boolean
						setopt(opt, r ? "yes" : "no");
				}
			} else {
				opt = &opt[1];

				// go through each option
				while(*opt) {
					// does the option exist?
					temp = v_format(va("$(optlong.%c)", *opt));
					if (temp[0]==0) {
						// no, throw a warning
						fprintf(stderr,
							"warning: unrecognized option '%c'\n", *opt);
						fflush(stderr);
					} else
						// yes, mark the option
						setopt(temp, "yes");

					// go to the next option
					opt++;
				}
			}
		} else {
			if ((p = strchr(opt, '=')) != (char *)0) {
				// a variable setting
				i_strncpy(buf, sizeof(buf), opt, p-opt);
				if (!strcmp(buf, "target"))
					v_array_push(v_find("targets"), &p[1]);
				else {
					fprintf(stderr,
						"warning: unrecognized setting '%s'\n", buf);
					fflush(stderr);
				}
			} else {
				// okay, just some file
				v_array_push(files, opt);
			}
		}
	}
}

void init(int argc, char **argv) {
	var_t v;

	// initialize the variable system
	initvars(argc, argv);

	// initialize the buffers system (used for parsing source files)
	b_init();

	// read the command line
	initdefopts();
	initopts(argc, argv);

	// if no targets were specified, host is implied
	v = v_find("targets");
	if (!strcmp(v_get(v), ""))
		v_array_push(v, v_getvar("hostconfig"));
}
